package com.softlab.okr.security;

import com.softlab.okr.config.LoaderSkipAuthURIApplication;
import com.softlab.okr.entity.Resource;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

/**
 * @author: zhangbo
 * @description: 权限认证
 * @date: 2021/9/9 14:56
 * @version: 1.0
 */
@Slf4j
@Component
public class RbacPermissionService {

  private static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();

  @Value("${spring.security.switch}")
  private boolean securitySwitch;

  @Autowired
  private IAuthenticationService authenticationService;

  public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
    UserDetail userDetail = authenticationService.getPrincipal();
    if (userDetail != null) {
      if (!securitySwitch) {
        log.debug("[未开启权限认证默认通过]");
        return true;
      }
      String requestURI = request.getRequestURI();
      //白名单默认通过
      if (pass(requestURI)) {
        log.debug("[白名单接口默认通过] requestURI:{}", requestURI);
        return true;
      }
      Collection<? extends GrantedAuthority> userAuthorities = userDetail.getAuthorities();
      if (userAuthorities == null) {
        return false;
      }
      Collection<ConfigAttribute> configAttributes = getConfigAttribute(request);
      if (configAttributes == null) {
        return false;
      }
      for (ConfigAttribute ca : configAttributes) {
        for (GrantedAuthority authority : userAuthorities) {
          // 如果匹配上了，代表当前登录用户是有该权限的，直接结束方法
          if (Objects.equals(authority.getAuthority(), ca.getAttribute())) {
            return true;
          }
        }
      }
    }
    return false;
  }

  private boolean pass(String uri) {
    Set<String> whiteUrls = LoaderSkipAuthURIApplication.getWhiteUrls();
    if (whiteUrls != null && !whiteUrls.isEmpty()) {
      AntPathMatcher matcher = new AntPathMatcher();
      for (String whiteUrl : whiteUrls) {
        if (matcher.match(whiteUrl, uri)) {
          return true;
        }
      }
    }
    return false;
  }

  private Collection<ConfigAttribute> getConfigAttribute(HttpServletRequest request) {
    for (Resource resource : MySecurityMetadataSource.getRESOURCES()) {
      String method = resource.getMethod();
      AntPathRequestMatcher ant = new AntPathRequestMatcher(resource.getPath());
      // 如果请求方法和请求路径都匹配上了，则代表找到了这个请求所需的授权规则
      if (request.getMethod().equals(method) && ant.matches(request)) {
        // 将我们权限资源id返回
        return Collections.singletonList(new SecurityConfig(resource.getResourceId().toString()));
      }
    }
    return null;
  }

}
